#include <stdio.h>
#include "key.h"
#include "systick.h"
#include "spi.h"
#include "hal_spi.h"
#include "clock_init.h"

static bool SPI_GpioConfig(void)
{
    /* gpio. */
    GPIO_Init_Type gpio_init;
    /* PB12 - SPI_CS. */
    gpio_init.Pins  = GPIO_PIN_12;
    gpio_init.PinMode  = GPIO_PinMode_Out_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &gpio_init);
    GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_15);
    GPIO_SetBits(GPIOB, gpio_init.Pins);

    /* PB13 - SPI_SCK. */
    gpio_init.Pins  = GPIO_PIN_13;
    gpio_init.PinMode  = GPIO_PinMode_AF_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &gpio_init);
    GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_5);

    /* PB14 - SPI_MISO. */
    gpio_init.Pins  = GPIO_PIN_14;
    gpio_init.PinMode  = GPIO_PinMode_In_PullUp;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &gpio_init);
    GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_5);

    /* PB15 - SPI_MOSI. */
    gpio_init.Pins  = GPIO_PIN_15;
    gpio_init.PinMode  = GPIO_PinMode_AF_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &gpio_init);
    GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_5);
    return true;
}

bool SPI_Config(void)
{
    SPI_GpioConfig();
    /* Setup SPI module. */
    SPI_Master_Init_Type spi_init;
    spi_init.ClockFreqHz = CLOCK_APB1_FREQ;
    spi_init.BaudRate = 400000u;
    spi_init.XferMode = SPI_XferMode_TxRx;
    spi_init.PolPha = SPI_PolPha_Alt1;
    spi_init.DataWidth = SPI_DataWidth_8b;
    spi_init.LSB = false;
    spi_init.AutoCS = true;
    SPI_InitMaster(SPI2, &spi_init);

    /* Enable SPI. */
    SPI_Enable(SPI2, true);
    return true;
}

static void SPI_WriteReadOnebyte(uint8_t w_data,uint8_t *r_data)
{
    while ( SPI_STATUS_TX_FULL & SPI_GetStatus(SPI2) )
    {}
    SPI_PutData(SPI2, w_data);
    while (0u == (SPI_STATUS_RX_DONE & SPI_GetStatus(SPI2)) )
    {}
    *r_data =  SPI_GetData(SPI2);
}

void SPI_WriteReadData(uint8_t *w_data,uint8_t *r_data,int len)
{
    GPIO_WriteBit(GPIOB,GPIO_PIN_12,0);
    while (len)
    {
        SPI_WriteReadOnebyte(*w_data++,r_data++);
        len--;
    }
    GPIO_WriteBit(GPIOB,GPIO_PIN_12,1);
}

#define CMD_JEDEC_ID          0x9f
#define CMD_MANUFACURER_ID    0x90

static void w25q32_read_manufacturer_id(uint16_t *id)
{
    uint8_t tx_data[6] = {CMD_MANUFACURER_ID ,0,0,0,0,0};
    uint8_t rx_data[6] = {0};
    SPI_WriteReadData(tx_data,rx_data,6);
	*id = (rx_data[4]<<8)|rx_data[5];
}


static void w25q32_read_jedec_id(uint16_t *id)
{
    uint8_t tx_data[4] = {CMD_JEDEC_ID ,0,0,0};
    uint8_t rx_data[4] = {0};
    SPI_WriteReadData(tx_data,rx_data,4);
	*id = (rx_data[2]<<8)|rx_data[3];
}

void SPI_Test(void)
{
    uint16_t id = 0;
    SPI_Config();
    w25q32_read_manufacturer_id(&id);
    printf("get manufacturer id == 0x%04x\r\n",id);
    w25q32_read_jedec_id(&id);
    printf("get jedec id == 0x%04x\r\n",id);
}